From 538bb4c06eb6074a702e9e577f1e0f5441c8b7bb Mon Sep 17 00:00:00 2001 From: Wei Liu Date: Mon, 5 Jun 2017 18:19:38 +0100 Subject: [PATCH] x86: move do_iret to pv/iret.c Signed-off-by: Wei Liu Reviewed-by: Andrew Cooper --- xen/arch/x86/pv/Makefile | 1 + xen/arch/x86/pv/iret.c | 91 +++++++++++++++++++++++++++++++++++++ xen/arch/x86/x86_64/traps.c | 56 ----------------------- 3 files changed, 92 insertions(+), 56 deletions(-) create mode 100644 xen/arch/x86/pv/iret.c diff --git a/xen/arch/x86/pv/Makefile b/xen/arch/x86/pv/Makefile index 939ea60bea..7e3da332d8 100644 --- a/xen/arch/x86/pv/Makefile +++ b/xen/arch/x86/pv/Makefile @@ -8,4 +8,5 @@ obj-y += emul-gate-op.o obj-y += emul-inv-op.o obj-y += emul-priv-op.o obj-bin-y += gpr_switch.o +obj-y += iret.o obj-y += misc-hypercalls.o diff --git a/xen/arch/x86/pv/iret.c b/xen/arch/x86/pv/iret.c new file mode 100644 index 0000000000..78763e6bc8 --- /dev/null +++ b/xen/arch/x86/pv/iret.c @@ -0,0 +1,91 @@ +/* + * pv/iret.c + * + * iret hypercall handling code + * + * This program is free software; you can redistribute it and/or + * modify it under the terms and conditions of the GNU General Public + * License, version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; If not, see + * . + */ + +#include +#include +#include + +#include +#include + +unsigned long do_iret(void) +{ + struct cpu_user_regs *regs = guest_cpu_user_regs(); + struct iret_context iret_saved; + struct vcpu *v = current; + + if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp, + sizeof(iret_saved))) ) + { + gprintk(XENLOG_ERR, + "Fault while reading IRET context from guest stack\n"); + goto exit_and_crash; + } + + /* Returning to user mode? */ + if ( (iret_saved.cs & 3) == 3 ) + { + if ( unlikely(pagetable_is_null(v->arch.guest_table_user)) ) + { + gprintk(XENLOG_ERR, + "Guest switching to user mode with no user page tables\n"); + goto exit_and_crash; + } + toggle_guest_mode(v); + } + + if ( VM_ASSIST(v->domain, architectural_iopl) ) + v->arch.pv_vcpu.iopl = iret_saved.rflags & X86_EFLAGS_IOPL; + + regs->rip = iret_saved.rip; + regs->cs = iret_saved.cs | 3; /* force guest privilege */ + regs->rflags = ((iret_saved.rflags & ~(X86_EFLAGS_IOPL|X86_EFLAGS_VM)) + | X86_EFLAGS_IF); + regs->rsp = iret_saved.rsp; + regs->ss = iret_saved.ss | 3; /* force guest privilege */ + + if ( !(iret_saved.flags & VGCF_in_syscall) ) + { + regs->entry_vector &= ~TRAP_syscall; + regs->r11 = iret_saved.r11; + regs->rcx = iret_saved.rcx; + } + + /* Restore upcall mask from supplied EFLAGS.IF. */ + vcpu_info(v, evtchn_upcall_mask) = !(iret_saved.rflags & X86_EFLAGS_IF); + + async_exception_cleanup(v); + + /* Saved %rax gets written back to regs->rax in entry.S. */ + return iret_saved.rax; + + exit_and_crash: + domain_crash(v->domain); + return 0; +} + +/* + * Local variables: + * mode: C + * c-file-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 36b694c605..4641bc6d06 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -254,62 +254,6 @@ void do_double_fault(struct cpu_user_regs *regs) panic("DOUBLE FAULT -- system shutdown"); } -unsigned long do_iret(void) -{ - struct cpu_user_regs *regs = guest_cpu_user_regs(); - struct iret_context iret_saved; - struct vcpu *v = current; - - if ( unlikely(copy_from_user(&iret_saved, (void *)regs->rsp, - sizeof(iret_saved))) ) - { - gprintk(XENLOG_ERR, - "Fault while reading IRET context from guest stack\n"); - goto exit_and_crash; - } - - /* Returning to user mode? */ - if ( (iret_saved.cs & 3) == 3 ) - { - if ( unlikely(pagetable_is_null(v->arch.guest_table_user)) ) - { - gprintk(XENLOG_ERR, - "Guest switching to user mode with no user page tables\n"); - goto exit_and_crash; - } - toggle_guest_mode(v); - } - - if ( VM_ASSIST(v->domain, architectural_iopl) ) - v->arch.pv_vcpu.iopl = iret_saved.rflags & X86_EFLAGS_IOPL; - - regs->rip = iret_saved.rip; - regs->cs = iret_saved.cs | 3; /* force guest privilege */ - regs->rflags = ((iret_saved.rflags & ~(X86_EFLAGS_IOPL|X86_EFLAGS_VM)) - | X86_EFLAGS_IF); - regs->rsp = iret_saved.rsp; - regs->ss = iret_saved.ss | 3; /* force guest privilege */ - - if ( !(iret_saved.flags & VGCF_in_syscall) ) - { - regs->entry_vector &= ~TRAP_syscall; - regs->r11 = iret_saved.r11; - regs->rcx = iret_saved.rcx; - } - - /* Restore upcall mask from supplied EFLAGS.IF. */ - vcpu_info(v, evtchn_upcall_mask) = !(iret_saved.rflags & X86_EFLAGS_IF); - - async_exception_cleanup(v); - - /* Saved %rax gets written back to regs->rax in entry.S. */ - return iret_saved.rax; - - exit_and_crash: - domain_crash(v->domain); - return 0; -} - static unsigned int write_stub_trampoline( unsigned char *stub, unsigned long stub_va, unsigned long stack_bottom, unsigned long target_va) -- 2.30.2